package cn.qingyun.gis.modules.baogan.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.qingyun.gis.exception.CommonException;
import cn.qingyun.gis.modules.baogan.dto.ParentPologon;
import cn.qingyun.gis.modules.baogan.dto.PolDto;
import cn.qingyun.gis.modules.baogan.dto.VisitTotalDto;
import cn.qingyun.gis.modules.baogan.entity.*;
import cn.qingyun.gis.modules.baogan.enums.CareObjectEnum;
import cn.qingyun.gis.modules.baogan.enums.OperationTypeEnum;
import cn.qingyun.gis.modules.baogan.mapper.*;
import cn.qingyun.gis.modules.baogan.service.MicroStreetDataService;
import cn.qingyun.gis.modules.baogan.service.MicrogridCareRecordService;
import cn.qingyun.gis.modules.baogan.vo.request.*;
import cn.qingyun.gis.modules.baogan.vo.response.*;
import cn.qingyun.gis.modules.scenes.contant.ScenesStatus;
import cn.qingyun.gis.modules.scenes.entity.PoiScenario;
import cn.qingyun.gis.modules.scenes.entity.UniAddrRegion;
import cn.qingyun.gis.modules.scenes.service.IUniAddrRegionService;
import cn.qingyun.gis.modules.scenes.mapper.PoiScenarioMapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
@DS("scenes_offensive")
public class MicroStreetDataServiceImpl extends ServiceImpl<MicroStreetDataMapper, MicroStreetData> implements MicroStreetDataService {
    @Resource
    private MicroStreetDataMapper streetDataMapper;
    @Resource
    private BaoganTeamMapper baoganTeamMapper;
    @Resource
    private MicrogridCareRecordMapper microgridCareRecordMapper;
    @Resource
    private CrmStaffMapper crmStaffMapper;
    @Resource
    private IUniAddrRegionService uniAddrRegionService;
    @Resource
    private PoiScenarioMapper poiScenarioMapper;
    @Resource
    private MicrogridCareRecordService careRecordService;
    @Resource
    private MicroStreetAuditLogService auditLogService;
    @Resource
    private MicroStreetAuditLogMapper microStreetAuditLogMapper;
    @Resource
    private MicroStreetDataService microStreetDataService;

    @Override
    public PolygonDetailRes selectStreetDetail(String microGridCode, String id, List<String> types) {
        // 异步获取面的审核状态
        CompletableFuture<MicroStreetAuditLog> reviewStateFuture = CompletableFuture.supplyAsync(() ->
                auditLogService.selectAuditLogByStreetId(id))
                .exceptionally(e -> {
                    log.error("获取面的审核状态异常: {}", e.getMessage(), e);
                    return null;
                });
        // 异步获取建筑数量
        CompletableFuture<Integer> buildingTotalFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetBuildingTotal(microGridCode, id,types))
                .exceptionally(e -> {
                    log.error("获取建筑数量异常: {}", e.getMessage(), e);
                    return null;
                });

        // 异步获取企业数量
        CompletableFuture<Integer> enterpriseTotalFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetEnterpriseTotal(microGridCode, id, types))
                .exceptionally(e -> {
                    log.error("异步获取企业数量: {}", e.getMessage(), e);
                    return null;
                });

        // 异步获取未随访和已随访数量
        CompletableFuture<VisitTotalDto> visitTotalFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetVisitTotal(microGridCode, id, types))
                .exceptionally(e -> {
                    log.error("异步获取未随访和已随访数量: {}", e.getMessage(), e);
                    return new VisitTotalDto(null, null);
                });
        //异步查询看管人员
        CompletableFuture<List<MicrogridCareRecordEntity>> custodiansFuture = CompletableFuture.supplyAsync(() ->
                        microgridCareRecordMapper.selectStreetCustodians(microGridCode, id))
                .exceptionally(e -> {
                    log.error("异步查询看管人员: {}", e.getMessage(), e);
                    return Collections.emptyList();
                });

        //异步查询变更面数据
        CompletableFuture<PolDto> logFuture = CompletableFuture.supplyAsync(() ->
                        microgridCareRecordMapper.selectWKTLogData(microGridCode, id))
                .exceptionally(e -> {
                    log.error("异步查询变更面数据: {}", e.getMessage(), e);
                    return new PolDto();
                });
        //查询微网格是否已经被看管划分
        CompletableFuture<Integer> cardFlagFuture = CompletableFuture.supplyAsync(() ->
                        microgridCareRecordMapper.slectMicroCareFlag(microGridCode, id))
                .exceptionally(e -> {
                    log.error("查询微网格是否已经被看管划分: {}", e.getMessage(), e);
                    return 0;
                });

        // 先查询主信息
        CompletableFuture<PolygonDetailRes> mainInfoFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetDetail(microGridCode, id))
                .exceptionally(e -> {
                    log.error("查询微网格详情异常: " + e.getMessage());
                    return new PolygonDetailRes();
                });

        // 在主信息查询完成后，查询父级信息
        CompletableFuture<ParentPologon> parentFuture = mainInfoFuture.thenCompose(res -> CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectParentPologon(res.getWkt())))
                .exceptionally(e -> {
                    log.error("查询父级信息异常: " + e.getMessage());
                    return new ParentPologon();
                });

        // 当所有异步操作都完成时，设置结果
        CompletableFuture<PolygonDetailRes> resultFuture = CompletableFuture.allOf(
                buildingTotalFuture, enterpriseTotalFuture, visitTotalFuture, custodiansFuture, logFuture, cardFlagFuture, parentFuture,reviewStateFuture
        ).thenCompose(v -> mainInfoFuture.thenApply(res -> {
            Integer buildingTotal = buildingTotalFuture.join();
            Integer enterpriseTotal = enterpriseTotalFuture.join();
            VisitTotalDto visitTotalDto = visitTotalFuture.join();
            List<MicrogridCareRecordEntity> careList = custodiansFuture.join();
            PolDto polDto = logFuture.join();
            Integer careFlag = cardFlagFuture.join();
            ParentPologon parentPologon = parentFuture.join();
            MicroStreetAuditLog microStreetAuditLog = reviewStateFuture.join();

            if (ObjectUtil.isNotNull(polDto)) {
                res.setPolData(polDto);
            }
            if (ObjectUtil.isNotNull(buildingTotal)) {
                res.setBuildingTotal(buildingTotal);
            }
            if (ObjectUtil.isNotNull(enterpriseTotal)) {
                res.setEnterpriseTotal(enterpriseTotal);
            }
            if (ObjectUtil.isNotNull(visitTotalDto)) {
                res.setNoVisitedTotal(visitTotalDto.getNoVisitedTotal());
                res.setVisitedTotal(visitTotalDto.getVisitedTotal());
            }
            if (ObjectUtil.isNotNull(careList)) {
                res.setCustodians(careList);
            }
            if (ObjectUtil.isNotNull(careFlag)) {
                res.setMicroCareFlag(careFlag);
            }
            if (ObjectUtil.isNotNull(parentPologon)) {
                res.setParentPologon(parentPologon);
            }
            if (ObjectUtil.isNotNull(microStreetAuditLog)) {
                res.setReviewState(microStreetAuditLog.getReviewState());
            }
            return res;
        }));

        try {
            return resultFuture.get();
        } catch (Exception e) {
            throw new RuntimeException("异步编排查询微网格详情错误={}", e);
        }
    }


    /**
     * 沿街面或绘制面-看管划分-查询团队人员
     *
     * @param request
     * @return
     */
    @Override
    public List<TeamItemVo> listTeam(GridCodeAndKeyListRequest request) {
        Assert.isTrue(StringUtil.isNotBlank(request.getMicroGridCode()), "微网格编码不能为空");
        //根据微网格查询看管的teamId
        LambdaQueryWrapper<MicrogridCareRecordEntity> careQueryWrapper = new LambdaQueryWrapper<>();
        careQueryWrapper
                .eq(MicrogridCareRecordEntity::getMicroGridCode, request.getMicroGridCode())
                .eq(MicrogridCareRecordEntity::getCareObject, CareObjectEnum.MICROGRID.getCode());
        if (ObjectUtil.isNotNull(request.getSceneType())) {
            careQueryWrapper.eq(MicrogridCareRecordEntity::getSceneType, request.getSceneType());
        }
        MicrogridCareRecordEntity microgridCareRecord = microgridCareRecordMapper.selectOne(careQueryWrapper);
        Assert.isTrue(!Objects.isNull(microgridCareRecord) && StringUtil.isNotBlank(microgridCareRecord.getTeamId()),
                "未查询到微网格对应的看管团队信息");

        List<TeamItemVo> list = baoganTeamMapper.listTeamByTeamIdAndKey(microgridCareRecord.getTeamId(), request.getKey());
        if (CollUtil.isNotEmpty(list)) {
            //查询每一个队伍下的成员列表
            list.forEach(team -> {
                LambdaQueryWrapper<BaoganTeam> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper
                        .eq(BaoganTeam::getTeamId, team.getTeamId())
                        .and(StringUtil.isNotBlank(request.getKey()), wq -> wq.like(BaoganTeam::getUserName, request.getKey()).or().like(BaoganTeam::getUserEmployeeNumber, request.getKey()));
                List<BaoganTeam> baoganTeams = baoganTeamMapper.selectList(queryWrapper);
                List<TeamMemberItemVo> memberItemVoList = baoganTeams.stream().map(item -> {
                    TeamMemberItemVo teamMemberItemVo = new TeamMemberItemVo();
                    BeanUtils.copyProperties(item, teamMemberItemVo);
                    return teamMemberItemVo;
                }).collect(Collectors.toList());
                team.setMemberList(memberItemVoList);
            });
        }
        return list;
    }

    @Override
    public Set<ChannelItemVo> listChannel(GridCodeAndKeyListRequest request) {
        LambdaQueryWrapper<CrmStaff> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(CrmStaff::getGridCode, request.getGridCode())
                .and(StringUtil.isNotBlank(request.getKey()), eq -> eq.like(CrmStaff::getChannelCode,
                        request.getKey())).or().like(CrmStaff::getChannelName, request.getKey());
        List<CrmStaff> crmStaffs = crmStaffMapper.selectList(queryWrapper);
        Set<ChannelItemVo> resultList = crmStaffs.stream().map(item -> {
            ChannelItemVo channelItemVo = new ChannelItemVo();
            BeanUtils.copyProperties(item, channelItemVo);
            return channelItemVo;
        }).collect(Collectors.toSet());
        return resultList;
    }

    @Override
    public StreetBaseResponse getWatchDivisionBaseInfo(IdRequest request) {
        StreetBaseResponse streetBaseResponse = new StreetBaseResponse();
        //计算面积
        Double area = streetDataMapper.getAreaById(request.getId());
        streetBaseResponse.setArea(area);
        //查询建筑数
        Integer buildCount = streetDataMapper.getBuildCount(request.getId());
        streetBaseResponse.setBuildCount(buildCount);
        //查询企业数
        Integer companyCount = streetDataMapper.getCompanyCount(request.getId());
        streetBaseResponse.setCompanyCount(companyCount);
        return streetBaseResponse;
    }

    @Override
    public List<EnterpriseResponse> selectEnterpriseList(String id) {
        return microgridCareRecordMapper.selectEnterpriseList(id);
    }

    /**
     * 查询绘制面中的建筑数、企业数
     *
     * @param request
     * @return
     */
    @Override
    public AoiBaseInfoVo getAoiBaseInfo(AoiBaseInfoGetRequest request) {
        AoiBaseInfoVo aoiBaseInfoVo = new AoiBaseInfoVo();
        //查询建筑数
        int buildCount = poiScenarioMapper.getAoiBaseInfo(request);
        aoiBaseInfoVo.setBuildCount(buildCount);
        //查询企业数
        int companyCount = poiScenarioMapper.getAoiBaseInfo(request);
        aoiBaseInfoVo.setCompanyCount(companyCount);
        //查询微网格是否已经看管划分
        Integer careFlag = microgridCareRecordMapper.selectCareFlagByMicroGridCode(request.getMicroGridCode());
        aoiBaseInfoVo.setCareFlag(careFlag);
        return aoiBaseInfoVo;
    }

    @Override
    public Page<MicroStreetAuditLogResp> selectAuditData(PendingAuditRequest request) {
        log.debug("查询待审核面数据列表入参{}", request);
        Page<MicroStreetAuditLogResp> respPage = new Page<>(request.getPageNum(), request.getPageSize());
        Integer level = uniAddrRegionService.selectLevel(request.getCode());
        return streetDataMapper.selectAuditData(respPage, request, level);
    }

    @Override
    public List<PerimeterDataResp> selectPerimeterData(PerimeterRequest request) {
        log.debug("开启周边入参{}", request);
        //根据中心点3千米范围的面与地市相交，取地市编码集合
        QueryWrapper<UniAddrRegion> wrapper = new QueryWrapper<>();
        wrapper.select("id", "code", "name", "level", "wkt").eq("code", request.getCode()).ne("state", -1);
        UniAddrRegion uniAddrRegion = uniAddrRegionService.getBaseMapper().selectOne(wrapper);
        if (uniAddrRegion == null || StringUtils.isEmpty(uniAddrRegion.getCode()) || uniAddrRegion.getLevel() == null) {
            throw new CommonException("未找到对应的区划数据！");
        }
        ArrayList<PerimeterDataResp> list = Lists.newArrayList();
        //1.先查面数据
        List<PerimeterDataResp> perimeterStreetData = streetDataMapper.selectPerimeterStreetData(request, uniAddrRegion.getCode(), uniAddrRegion.getLevel());
        list.addAll(perimeterStreetData);
        //2.再查点数据
        List<PerimeterDataResp> perimeterPoiData = poiScenarioMapper.selectPerimeterPoiData(request, uniAddrRegion.getCode(), uniAddrRegion.getLevel());
        list.addAll(perimeterPoiData);
        //处理商业综合体类型-->变为商务楼宇
        list.forEach(data -> {
            if (data.getType().equals(ScenesStatus.COMPLEX.getDesc())){
                data.setType(ScenesStatus.BUSINESS.getDesc());
            }
        });
        log.debug("周边返回的集合大小{}", list.size());
        return list;
    }

    @Override
    public List<PoiScenario> selectPerimeterPointData(PerimeterPointRequest request) {
        log.info("周边查询查看具体面下的点数据入参{}",request);
        List<String> types = request.getTypes();
        if (types.contains(ScenesStatus.BUSINESS.getDesc())) {
            types.add(ScenesStatus.COMPLEX.getDesc());
        }
        Integer level = uniAddrRegionService.selectLevel(request.getCode());
        List<PoiScenario> list = poiScenarioMapper.selectPerimeterPointData(request, level);
        //处理商业综合体类型-->变为商务楼宇
        list.forEach(poiScenario -> {
            if (poiScenario.getType().equals(ScenesStatus.COMPLEX.getDesc())){
                poiScenario.setType(ScenesStatus.BUSINESS.getDesc());
            }
        });
        return list;
    }

    @DS("scenes_offensive")
    @Override
    public PolygonDetailRes getReviewingDetail(String id, String microGridCode, List<String> types) {
        // 异步查询企业总数
        CompletableFuture<Integer> enterpriseTotalFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetEnterpriseTotal(microGridCode, id, types))
                .exceptionally(e -> {
                    log.error("审核面详情查询-----获取企业数量异常: " + e);
                    throw new CommonException("审核面详情查询-----获取企业数量异常");
                });
        // 异步查询建筑总数
        CompletableFuture<Integer> buildingTotalFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetBuildingTotal(microGridCode, id, types))
                .exceptionally(e -> {
                    log.error("审核面详情查询-----获取建筑数量异常: " + e);
                    throw new CommonException("审核面详情查询-----获取建筑数量异常");
                });
        // 异步查询未随访和已随访数量
        CompletableFuture<VisitTotalDto> visitTotalFuture = CompletableFuture.supplyAsync(() ->
                        streetDataMapper.selectStreetVisitTotal(microGridCode, id,types))
                .exceptionally(e -> {
                    log.error("审核面详情查询-----获取未随访和已随访数量异常: " + e);
                    throw new CommonException("审核面详情查询-----获取未随访和已随访数量异常");
                });
        // 异步查询看管人员
        CompletableFuture<List<MicrogridCareRecordEntity>> custodiansFuture = CompletableFuture.supplyAsync(() ->
                        microgridCareRecordMapper.selectMGCustodians(microGridCode, id))
                .exceptionally(e -> {
                    log.error("审核面详情查询-----查询看管人员异常: " + e);
                    throw new CommonException("审核面详情查询-----查询看管人员异常");
                });
        //查询审核表
        CompletableFuture<MicroStreetAuditLog> logFuture = CompletableFuture.supplyAsync(() ->
                        microStreetAuditLogMapper.selectOneByStreetId(id))
                .exceptionally(e -> {
                    log.error("审核面详情查询-----审核记录查询异常: " + e);
                    throw new CommonException("审核面详情查询-----审核记录查询异常");
                });
        // 在 logFuture 完成后，查询原始 WKT
        CompletableFuture<PolDto> wktFuture = logFuture.thenCompose(oldLog -> {
            if (ObjectUtil.isNotNull(oldLog) && oldLog.getOperationType().equals(OperationTypeEnum.UPDATE.getCode())) {
                return CompletableFuture.supplyAsync(() ->
                                careRecordService.selectWKTLogData(microGridCode, id))
                        .exceptionally(e -> {
                            log.error("审核面详情查询-----查询原始 WKT: " + e);
                           throw new CommonException("审核面详情查询-----查询原始 WKT");
                        });
            } else {
                return CompletableFuture.completedFuture(new PolDto());
            }
        });
        // 在 logFuture 完成后，查询父级信息
        CompletableFuture<ParentPologon> parentFuture = logFuture.thenCompose(oldLog -> {
            if (ObjectUtil.isNotNull(oldLog) && oldLog.getOperationType().equals(OperationTypeEnum.UPDATE.getCode())) {
                return wktFuture.thenCompose(wktData -> CompletableFuture.supplyAsync(() ->
                                streetDataMapper.selectParentPologon(wktData.getNewWkt()))
                        .exceptionally(e -> {
                            log.error("审核面详情查询-----查询父级信息异常: " + e);
                            throw new CommonException("审核面详情查询-----查询父级信息异常");
                        }));
            } else {
                return CompletableFuture.completedFuture(new ParentPologon());
            }
        });
        // 当所有异步操作都完成时，设置结果
        CompletableFuture<PolygonDetailRes> resultFuture = CompletableFuture.allOf(
                enterpriseTotalFuture, buildingTotalFuture, visitTotalFuture, custodiansFuture, wktFuture
                ,parentFuture
        ).thenApply(v -> {
            PolygonDetailRes streetData = streetDataMapper.selectStreetDetail(microGridCode, id);
            if (ObjectUtil.isNull(streetData)) {
                throw new CommonException("审核面详情查询-----查询街道详情为空");
            }
            Integer enterpriseTotal = enterpriseTotalFuture.join();
            Integer buildingTotal = buildingTotalFuture.join();
            VisitTotalDto visitTotalDto = visitTotalFuture.join();
            List<MicrogridCareRecordEntity> custodians = custodiansFuture.join();
            PolDto wktData = wktFuture.join();
            ParentPologon parentPologon = parentFuture.join();
            MicroStreetAuditLog auditLog = logFuture.join();

            streetData.setEnterpriseTotal(enterpriseTotal);
            streetData.setBuildingTotal(buildingTotal);
            streetData.setNoVisitedTotal(visitTotalDto.getNoVisitedTotal());
            streetData.setVisitedTotal(visitTotalDto.getVisitedTotal());
            streetData.setCustodians(custodians);
            streetData.setOperationType(auditLog.getOperationType());
            if (ObjectUtil.isNotNull(wktData)) {
                streetData.setPolData(wktData);
            }
            if (ObjectUtil.isNotNull(parentPologon)){
                streetData.setParentPologon(parentPologon);
            }
            return streetData;
        });
        try {
            return resultFuture.get();
        } catch (Exception e) {
            log.error("审核面详情查询-----查询微网格详情异常:",e);
            throw new RuntimeException("审核面详情查询-----异步编排查询微网格详情错误: " + e.getMessage(), e);
        }
    }

    @Override
    public void updateWKT(MicroStreetData streetData) {
        this.baseMapper.updateWkt(streetData);
    }

    @Override
    public MicroStreetData selectOneById(String id) {
        return this.baseMapper.MicroStreetData(id);
    }

    @Override
    public boolean saveBoundary(MicroStreetData data) {
        return this.baseMapper.saveBoundary(data);
    }

    @Override
    public MicroStreetData selectParentByWkt(String wkt) {
        return this.baseMapper.selectParentByWkt(wkt);
    }

    @Override
    public List<String> selectPointInPolygon(String wkt) {
        return this.baseMapper.selectPointInPolygon(wkt);
    }

    @Override
    public void updateParentIdById(List<String> pointIds, String id) {
        this.baseMapper.updateParentIdById(pointIds,id);
    }

    @Override
    public void updateParentIdNullById(List<String> pointIds, String id) {
        this.baseMapper.updateParentIdNullById(pointIds,id);
    }

    @Override
    public AoiBaseInfoVo getQHBaseInfo(AoiBaseInfoGetRequest request) {
        AoiBaseInfoVo aoiBaseInfoVo = new AoiBaseInfoVo();
        //查询建筑数
        int buildCount = poiScenarioMapper.getAoiBaseInfo(request);
        aoiBaseInfoVo.setBuildCount(buildCount);
        //查询企业数
        int companyCount = poiScenarioMapper.getAoiBaseInfo(request);
        aoiBaseInfoVo.setCompanyCount(companyCount);
        //查询微网格是否已经看管划分
        Integer careFlag = microgridCareRecordMapper.selectCareFlagByMicroGridCode(request.getMicroGridCode());
        aoiBaseInfoVo.setCareFlag(careFlag);
        //查询有效商街数量
        Integer streetCount = this.baseMapper.getStreetCount(request);
        aoiBaseInfoVo.setStreetCount(streetCount);
        return aoiBaseInfoVo;
    }

    @Override
    public List<DataResponse> selectDataResponse(MicroDataRequest request,String wkt) {
        return streetDataMapper.selectDataResponseList(request,wkt);
    }

    @Override
    public List<StreetDataRes> selectDateList(BigDecimal rtLon, BigDecimal rtLat, BigDecimal lbLon, BigDecimal lbLat, String text, List<String> types) {
        return streetDataMapper.selectDateList(rtLon,rtLat,lbLon,lbLat,text,types);
    }

    @Override
    public List<DataResponse> selectRepeatDataList(RepeatPolygonRequest request) {
        return streetDataMapper.selectRepeatDataList(request);
    }

    @Override
    public MicroStreetData getMicroStreetDataById(String id) {
        return streetDataMapper.getMicroStreetDataById(id);
    }
}
